#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "CuTest.h"

#include "sprout.h"

/**
 * 1.期望将 Object 转为 JSON 字符串 {}
 */
void test_object_to_str(CuTest *tc)
{
    const char *expected = "{}";
    Object obj = {};
    char *actual = object_to_str(&obj);
    CuAssertStrEquals(tc, expected, actual);

    if (actual)
    {
        free(actual);
    }
}

/**
 * 2.期望将 JSON 字符串 {   } 转为 Object
 */
void test_str_to_object(CuTest *tc)
{
    Object *actual = str_to_object(" \
         {   \
          }");
    CuAssertPtrNotNull(tc, actual);
    CuAssertPtrEquals(tc, actual->curr, NULL);
    CuAssertPtrEquals(tc, actual->next, NULL);

    if (actual)
    {
        free(actual);
    }
}

/**
 * 3.期望将 Array 转为 JSON 字符串 []
 */
void test_array_to_str(CuTest *tc)
{
    const char *expected = "[]";
    Array arr = {NULL, NULL};
    char *actual = array_to_str(&arr);
    CuAssertStrEquals(tc, expected, actual);

    if (actual)
    {
        free(actual);
    }
}

/**
 * 4.期望将 JSON 字符串 [  ] 转为 Array
 */
void test_str_to_array(CuTest *tc)
{
    Array *actual = str_to_array(" \
          [   \
     ]");
    CuAssertPtrNotNull(tc, actual);
    CuAssertPtrEquals(tc, actual->curr, NULL);
    CuAssertPtrEquals(tc, actual->next, NULL);

    if (actual)
    {
        free(actual);
    }
}

/**
 * 5.期望将 JSON array [{}, []] 转为 Array 对象
 */
void test_json_array_to_c_array(CuTest *tc)
{
    const char *use_case = "[{}, []]";
    Array *actual = json_array_to_c_array(use_case);
    CuAssertPtrNotNull(tc, actual);

    if (actual)
    {
        free(actual);
    }
}
/**
 * 6.期望将 Array 对象转为 JSON array [{}, []]
 */
void test_c_array_to_json_array(CuTest *tc)
{
    const char *expected = "[{}, []]";
    // 构造一个包含对象和数组的 Array 对象
    Array arr = {NULL, NULL};
    char *actual = c_array_to_json_array(&arr);
    CuAssertStrEquals(tc, expected, actual);

    if (actual)
    {
        free(actual);
    }
}

/**
 * 7.期望将 JSON string 转为 char *
 */
void test_json_string_to_c_string(CuTest *tc)
{
    const char *expected = "_\\_/_\b_\f_\n_\r_\t_一_𠆣";
    const char *use_case = "\"_\\_/_\b_\f_\n_\r_\t_一_𠆣\"";
    char *actual = json_string_to_c_string(use_case);
    CuAssertPtrNotNull(tc, actual);
    CuAssertStrEquals(tc, expected, actual);

    if (actual)
    {
        free(actual);
    }
}

/**
 * 8.期望将 char * 转为 JSON string
 */
void test_c_string_to_json_string(CuTest *tc)
{
    const char *expected = "\"foo\"";
    const char *str = "foo";
    char *actual = c_string_to_json_string(str);
    CuAssertStrEquals(tc, expected, actual);

    if (actual)
    {
        free(actual);
    }
}

int main(void)
{
    CuString *output = CuStringNew();
    CuSuite *suite = CuSuiteNew();

    SUITE_ADD_TEST(suite, test_object_to_str);
    SUITE_ADD_TEST(suite, test_str_to_object);
    SUITE_ADD_TEST(suite, test_str_to_array);
    SUITE_ADD_TEST(suite, test_array_to_str);
    SUITE_ADD_TEST(suite, test_json_array_to_c_array);
    SUITE_ADD_TEST(suite, test_c_array_to_json_array);
    SUITE_ADD_TEST(suite, test_json_string_to_c_string);
    SUITE_ADD_TEST(suite, test_c_string_to_json_string);
    CuSuiteRun(suite);
    CuSuiteSummary(suite, output);
    CuSuiteDetails(suite, output);
    printf("%s\n", output->buffer);

    return 0;
}
